package userControl

import (
	"fmt"
	"github.com/fwhezfwhez/errorx"
	"github.com/fwhezfwhez/model_convert/util"
	"github.com/gin-gonic/gin"
	"helloworld/dependence"
	"helloworld/dependence/db"
	"helloworld/dependence/redistool"
	"helloworld/module/user/userModel"
	"helloworld/module/user/userService"
	"strconv"
	"time"
)

func GetUserList(c *gin.Context) {
	type Param struct {
		GameId int `json:"game_id" binding:"required"`
	}
	var param Param
	if e := c.Bind(&param); e != nil {
		fmt.Println(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	list, e := userService.GetUserList(param.GameId)
	if e != nil {
		fmt.Println(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	c.JSON(200, gin.H{"data": list})
}

// Auto generated by github.com/fwhezfwhez/model_convert.GenerateCRUD. You might need import:
// "github.com/gin-gonic/gin"
// "github.com/fwhezfwhez/errorx"
// "github.com/fwhezfwhez/model_convert/util"
//
// "package/path/to/db.DB"
// "package/path/to/userModel.UserInfo"
// "package/path/to/${redis_conn}"
//
// Use codes below like:
/*
        r := gin.Default()
        r.POST("/user-info/", userControl.HTTPAddUserInfo)
        r.PATCH("/user-info/:id/", userControl.HTTPUpdateUserInfo)
        r.DELETE("/user-info/:id/", userControl.HTTPDeleteUserInfo)
        r.GET("/user-info/", userControl.HTTPListUserInfo)
        r.GET("/user-info/:id/", userControl.HTTPGetUserInfo)
        r.POST("/user-info-cache-profile/", userControl.HTTPProfileCacheUserInfo)
*/
// Auto generate by github.com/fwhezfwhez/model_convert.GenerateAddOneAPI().
func HTTPAddUserInfo(c *gin.Context) {
	var param userModel.UserInfo
	if e := c.Bind(&param); e != nil {
		c.JSON(400, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if e := db.DB.Model(&userModel.UserInfo{}).Create(&param).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if param.RedisKey() != "" {
		conn := redistool.RedisPool.Get()
		defer conn.Close()
		param.DeleteFromRedis(conn)
	}
	c.JSON(200, gin.H{"message": "success", "data": param})
}

// Auto generate by github.com/fwhezfwhez/model_convert.GenerateListAPI().
func HTTPListUserInfo(c *gin.Context) {

	var engine = db.DB.Model(&userModel.UserInfo{})

	id := c.DefaultQuery("id", "")
	if id != "" {
		engine = engine.Where("id = ?", id)
	}
	userId := c.DefaultQuery("user_id", "")
	if userId != "" {
		engine = engine.Where("user_id = ?", userId)
	}
	openId := c.DefaultQuery("open_id", "")
	if openId != "" {
		engine = engine.Where("open_id = ?", openId)
	}
	unionId := c.DefaultQuery("union_id", "")
	if unionId != "" {
		engine = engine.Where("union_id = ?", unionId)
	}
	userName := c.DefaultQuery("user_name", "")
	if userName != "" {
		engine = engine.Where("user_name = ?", userName)
	}
	headerUrl := c.DefaultQuery("header_url", "")
	if headerUrl != "" {
		engine = engine.Where("header_url = ?", headerUrl)
	}
	sex := c.DefaultQuery("sex", "")
	if sex != "" {
		engine = engine.Where("sex = ?", sex)
	}
	gameId := c.DefaultQuery("game_id", "")
	if gameId != "" {
		engine = engine.Where("game_id = ?", gameId)
	}
	lastLoginTimeStartTimeStr := c.DefaultQuery("last_login_time_start", "")
	lastLoginTimeEndTimeStr := c.DefaultQuery("last_login_time_end", "")
	var lastLoginTimeStart, lastLoginTimeEnd time.Time
	if lastLoginTimeStartTimeStr != "" && lastLoginTimeEndTimeStr != "" {
		var e error
		lastLoginTimeStart, e = time.ParseInLocation("2006-01-02", lastLoginTimeStartTimeStr, time.Local)
		if e != nil {
			c.JSON(400, gin.H{"message": e.Error()})
			return
		}
		lastLoginTimeEnd, e = time.ParseInLocation("2006-01-02", lastLoginTimeEndTimeStr, time.Local)
		if e != nil {
			c.JSON(400, gin.H{"message": e.Error()})
			return
		}
		engine = engine.Where("last_login_time between ? and ?", lastLoginTimeStart, lastLoginTimeEnd.AddDate(0, 0, 1))
	}
	createdAtStartTimeStr := c.DefaultQuery("created_at_start", "")
	createdAtEndTimeStr := c.DefaultQuery("created_at_end", "")
	var createdAtStart, createdAtEnd time.Time
	if createdAtStartTimeStr != "" && createdAtEndTimeStr != "" {
		var e error
		createdAtStart, e = time.ParseInLocation("2006-01-02", createdAtStartTimeStr, time.Local)
		if e != nil {
			c.JSON(400, gin.H{"message": e.Error()})
			return
		}
		createdAtEnd, e = time.ParseInLocation("2006-01-02", createdAtEndTimeStr, time.Local)
		if e != nil {
			c.JSON(400, gin.H{"message": e.Error()})
			return
		}
		engine = engine.Where("created_at between ? and ?", createdAtStart, createdAtEnd.AddDate(0, 0, 1))
	}
	platformId := c.DefaultQuery("platform_id", "")
	if platformId != "" {
		engine = engine.Where("platform_id = ?", platformId)
	}
	channel := c.DefaultQuery("channel", "")
	if channel != "" {
		engine = engine.Where("channel = ?", channel)
	}
	isRobot := c.DefaultQuery("is_robot", "")
	if isRobot != "" {
		engine = engine.Where("is_robot = ?", isRobot)
	}
	lastLastLoginTimeStartTimeStr := c.DefaultQuery("last_last_login_time_start", "")
	lastLastLoginTimeEndTimeStr := c.DefaultQuery("last_last_login_time_end", "")
	var lastLastLoginTimeStart, lastLastLoginTimeEnd time.Time
	if lastLastLoginTimeStartTimeStr != "" && lastLastLoginTimeEndTimeStr != "" {
		var e error
		lastLastLoginTimeStart, e = time.ParseInLocation("2006-01-02", lastLastLoginTimeStartTimeStr, time.Local)
		if e != nil {
			c.JSON(400, gin.H{"message": e.Error()})
			return
		}
		lastLastLoginTimeEnd, e = time.ParseInLocation("2006-01-02", lastLastLoginTimeEndTimeStr, time.Local)
		if e != nil {
			c.JSON(400, gin.H{"message": e.Error()})
			return
		}
		engine = engine.Where("last_last_login_time between ? and ?", lastLastLoginTimeStart, lastLastLoginTimeEnd.AddDate(0, 0, 1))
	}
	phone := c.DefaultQuery("phone", "")
	if phone != "" {
		engine = engine.Where("phone = ?", phone)
	}
	page := c.DefaultQuery("page", "1")
	size := c.DefaultQuery("size", "20")
	orderBy := c.DefaultQuery("order_by", "")
	var count int
	if e := engine.Count(&count).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	var list = make([]userModel.UserInfo, 0, 20)
	if count == 0 {
		c.JSON(200, gin.H{"message": "success", "count": 0, "data": list})
		return
	}

	limit, offset := util.ToLimitOffset(size, page, count)
	engine = engine.Limit(limit).Offset(offset)
	if orderBy != "" {
		engine = engine.Order(util.GenerateOrderBy(orderBy))
	}
	if e := engine.Find(&list).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	c.JSON(200, gin.H{"message": "success", "count": count, "data": list})
}

// Auto generate by github.com/fwhezfwhez/model_convert.GenerateGetOneAPI().
func HTTPGetUserInfo(c *gin.Context) {
	id := c.Param("id")
	idInt, e := strconv.Atoi(id)
	if e != nil {
		c.JSON(400, gin.H{"message": fmt.Sprintf("param 'id' requires int but got %s", id)})
		return
	}
	var count int
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", idInt).Count(&count).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if count == 0 {
		c.JSON(200, gin.H{"message": fmt.Sprintf("id '%s' record not found", id)})
		return
	}
	var instance userModel.UserInfo
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", id).First(&instance).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	c.JSON(200, gin.H{"message": "success", "data": instance})
}

// Auto generate by github.com/fwhezfwhez/model_convert.GenerateUpdateOneAPI().
func HTTPUpdateUserInfo(c *gin.Context) {
	id := c.Param("id")
	idInt, e := strconv.Atoi(id)
	if e != nil {
		c.JSON(400, gin.H{"message": fmt.Sprintf("param 'id' requires int but got %s", id)})
		return
	}
	var count int
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", idInt).Count(&count).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if count == 0 {
		c.JSON(200, gin.H{"message": fmt.Sprintf("id '%s' record not found", id)})
		return
	}
	var param userModel.UserInfo
	if e := c.Bind(&param); e != nil {
		c.JSON(400, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	var instance userModel.UserInfo
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", idInt).First(&instance).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}

	tran := db.DB.Begin()
	// handle none-zero
	if e := tran.Model(&userModel.UserInfo{}).Where("id=?", id).Updates(param).Error; e != nil {
		tran.Rollback()
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}

	// handle zero

	var m = make(map[string]interface{})

	if param.UserId == 12306 {
		m["user_id"] = 0
	}

	if param.OpenId == "12306" {
		m["open_id"] = ""
	}

	if param.UnionId == "12306" {
		m["union_id"] = ""
	}

	if param.UserName == "12306" {
		m["user_name"] = ""
	}

	if param.HeaderUrl == "12306" {
		m["header_url"] = ""
	}

	if param.Sex == 12306 {
		m["sex"] = 0
	}

	if param.GameId == 12306 {
		m["game_id"] = 0
	}

	if param.PlatformId == 12306 {
		m["platform_id"] = 0
	}

	if param.Channel == "12306" {
		m["channel"] = ""
	}

	if param.IsRobot == 12306 {
		m["is_robot"] = 0
	}

	if param.Phone == "12306" {
		m["phone"] = ""
	}

	if len(m) > 0 {
		if e := tran.Model(&userModel.UserInfo{}).Where("id=?", id).Updates(m).Error; e != nil {
			tran.Rollback()
			dependence.SaveError(errorx.Wrap(e))
			c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
			return
		}
	}

	tran.Commit()
	if instance.RedisKey() != "" {
		conn := redistool.RedisPool.Get()
		defer conn.Close()
		instance.DeleteFromRedis(conn)
	}
	c.JSON(200, gin.H{"message": "success"})
}

// Auto generate by github.com/fwhezfwhez/model_convert.GenerateDeleteOneAPI().
func HTTPDeleteUserInfo(c *gin.Context) {
	id := c.Param("id")
	idInt, e := strconv.Atoi(id)
	if e != nil {
		c.JSON(400, gin.H{"message": fmt.Sprintf("param 'id' requires int but got %s", id)})
		return
	}
	var count int
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", idInt).Count(&count).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if count == 0 {
		c.JSON(200, gin.H{"message": fmt.Sprintf("id '%s' record not found", id)})
		return
	}
	var instance userModel.UserInfo
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", idInt).First(&instance).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if e := db.DB.Model(&userModel.UserInfo{}).Where("id=?", id).Delete(&userModel.UserInfo{}).Error; e != nil {
		dependence.SaveError(errorx.Wrap(e))
		c.JSON(500, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if instance.RedisKey() != "" {
		conn := redistool.RedisPool.Get()
		defer conn.Close()
		instance.DeleteFromRedis(conn)
	}
	c.JSON(200, gin.H{"message": "success"})
}

// Auto generate by github.com/fwhezfwhez/model_convert.GenerateCacheProfileAPI().
// You might import /path/to/userModel.
func HTTPProfileCacheUserInfo(c *gin.Context) {
	type Param struct {
		Command string `json:"commond"`
		Key     string `json:"key"`
	}
	var param Param
	if e := c.Bind(&param); e != nil {
		c.JSON(400, gin.H{"message": errorx.Wrap(e).Error()})
		return
	}
	if param.Command == "" && param.Key == "" {
		c.JSON(200, gin.H{
			"message":            "success",
			"cache_name":         "UserInfo",
			"cache_length":       len(userModel.UserInfoCache),
			"cache_order_length": len(userModel.UserInfoCacheKeyOrder),
			"cache_config": gin.H{
				"delete_rate":  userModel.UserInfoDeleteRate,
				"max_length":   userModel.UserInfoCacheMaxLength,
				"cache_switch": userModel.UserInfoCacheSwitch,
				"key_format":   userModel.UserInfoRedisKeyFormat,
			},
			"array_cache_name":         "ArrayUserInfo",
			"array_cache_length":       len(userModel.ArrayUserInfoCache),
			"array_cache_order_length": len(userModel.ArrayUserInfoCacheKeyOrder),
			"array_cache_config": gin.H{
				"delete_rate":      userModel.ArrayUserInfoDeleteRate,
				"max_length":       userModel.ArrayUserInfoCacheMaxLength,
				"cache_switch":     userModel.ArrayUserInfoCacheSwitch,
				"array_key_format": userModel.ArrayUserInfoRedisKeyFormat,
			},
		})
		return
	}
	if param.Key != "" && param.Command == "" {
		userModel.UserInfoCacheLock.RLock()
		defer userModel.UserInfoCacheLock.RUnlock()
		v, ok := userModel.UserInfoCache[param.Key]
		if ok {
			c.JSON(200, gin.H{
				"message": "success",
				"tip":     "hit in userModel.UserInfoCache",
				"key":     param.Key,
				"value":   v,
			})
			return
		}
		userModel.ArrayUserInfoCacheLock.RLock()
		defer userModel.ArrayUserInfoCacheLock.RUnlock()
		v2, ok2 := userModel.ArrayUserInfoCache[param.Key]
		if ok2 {
			c.JSON(200, gin.H{
				"message": "success",
				"tip":     "hit in ArrayUserInfoCache",
				"key":     param.Key,
				"value":   v2,
			})
			return
		}
		c.JSON(200, gin.H{
			"message": "success",
			"tip":     "hit none nether in userModel.UserInfoCache nor ArrayUserInfoCache",
			"key":     param.Key,
			"value":   v2,
		})
		return
	}
	c.JSON(200, gin.H{"message": "success", "tip": "I'm confused, maybe you can put nothing in body"})
}
